package com.ashin.service.impl;

import com.alibaba.dashscope.exception.NoApiKeyException;
import com.ashin.client.LinkAiClient;
import com.ashin.client.QianWenClient;
import com.ashin.entity.bo.ChatBO;
import com.ashin.exception.ChatException;
import com.ashin.service.InteractService;
import com.ashin.util.BotUtil;
import com.ashin.util.FileUtils;
import com.theokanning.openai.OpenAiHttpException;
import com.theokanning.openai.completion.chat.ChatCompletionRequest;
import com.theokanning.openai.completion.chat.ChatMessage;
import io.github.mzdluo123.silk4j.AudioUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import static io.github.mzdluo123.silk4j.AudioUtils.mp3ToSilk;

/**
 * 交互服务impl
 *
 * @author ashinnotfound
 * @date 2022/12/10
 */
@Service
@Slf4j
public class InteractServiceImpl implements InteractService {

    @Resource
    private BotUtil botUtil;
    @Resource
    LinkAiClient linkAiClient;
    @Resource
    private QianWenClient qianWenClient;
    @Override
    public String chat(ChatBO chatBO) throws ChatException {

        List<ChatMessage> prompt = botUtil.buildPrompt(chatBO.getSessionId(), chatBO.getPrompt());
        if (prompt == null){
            throw new ChatException("提问失败: 提问内容过长");
        }

        //向gpt提问
        ChatCompletionRequest completionRequest = botUtil.getCompletionRequestBuilder().messages(prompt).build();
        ChatMessage answer = null;
        try {
            answer = botUtil.getOpenAiService().createChatCompletion(completionRequest).getChoices().get(0).getMessage();
        }catch (OpenAiHttpException e){
            log.error("向gpt提问失败，提问内容：{}，\n原因：{}\n", chatBO.getPrompt(), e.getMessage(), e);
            // https://platform.openai.com/docs/guides/error-codes/api-errors
            if (401 == e.statusCode){
                throw new ChatException("提问失败: 无效的apikey, 请确保apikey正确且你拥有权限");
            }else if(429 == e.statusCode){
                throw new ChatException("提问过于频繁 或者 apikey余额不足");
            }else if(500 == e.statusCode) {
                throw new ChatException("提问失败: openai服务异常, 请稍后重试");
            }else if(503 == e.statusCode) {
                throw new ChatException("提问失败: openai服务过载, 请稍后重试");
            }
        }
        if (null == answer){
            throw new ChatException("提问失败: 未知错误, 若频繁出现请提issue");
        }

        prompt.add(answer);

        return answer.getContent().trim();
    }

    @Override
    public String linkAiChat(ChatBO chatBO, boolean useGpt4) throws ChatException {

        List<ChatMessage> prompt = botUtil.buildPrompt(chatBO.getSessionId(), chatBO.getPrompt());
        if (prompt == null){
            throw new ChatException("提问失败: 提问内容过长");
        }
        //向gpt提问
        String content = linkAiClient.send(prompt,useGpt4);
        ChatMessage answer = new ChatMessage("assistant",content);
        prompt.add(answer);

        return answer.getContent().trim();
    }
    @Override
    public String qwenChat(ChatBO chatBO) throws ChatException {

        List<ChatMessage> prompt = botUtil.buildPrompt(chatBO.getSessionId(), chatBO.getPrompt());
        if (prompt == null){
            throw new ChatException("提问失败: 提问内容过长");
        }
        //向gpt提问
        String content = qianWenClient.send(prompt);
        ChatMessage answer = new ChatMessage("assistant",content);
        prompt.add(answer);

        return answer.getContent().trim();
    }

    @Override
    public String sdImageChat(ChatBO chatBO, String prompt) throws ChatException {
        String positive = prompt;
        String negative = "";
        int indexOfPos = prompt.indexOf("#positive");
        if(indexOfPos>=0){
            int indexOfNeg = prompt.indexOf("#negative");
            if(indexOfNeg>=0){
                positive = prompt.substring(indexOfPos+9,indexOfNeg);
                negative = prompt.substring(indexOfNeg+9,prompt.length());
            }
            else positive = prompt.substring(indexOfPos+9);
        }
        try {
            return qianWenClient.genImage(positive,negative);
        } catch (NoApiKeyException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public String localImageChat(ChatBO chatBO, String prompt) throws ChatException {
        if(prompt!=null && (prompt.contains("涩图")))
            return FileUtils.getRandomImageFiles("data");

        return FileUtils.getRandomImageFiles("data/pictures");
    }

    /**语音问答
     * 1.生成文本
     * 2.文本转MP3语音
     * 3.mp3语音转silk语音
     * 4.返回silk文件路径
     * */
    @Override
    public File audioChat(String model,ChatBO chatBO) throws ChatException {

        List<ChatMessage> prompt = botUtil.buildPrompt(chatBO.getSessionId(), chatBO.getPrompt());
        if (prompt == null){
            throw new ChatException("提问失败: 提问内容过长");
        }
        //向gpt提问
        String content = qianWenClient.send(prompt);
        ChatMessage answer = new ChatMessage("assistant",content);
        prompt.add(answer);
        File silk =  textToAudio(content.trim(),content.trim());
        return silk;
    }
    @Override
    public File textToAudio(String model,String text){
        String mp3AudioFilePath = qianWenClient.SyncAudioDataToFile(text,model);
        File mp3File = new File(mp3AudioFilePath);
        try {
            AudioUtils.init(new File("data/voice"));
           return AudioUtils.mp3ToSilk(mp3File);
        } catch (IOException e) {
        }
        return null;
    }

}
